package com.ruoyi.web.controller.business;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.ruoyi.common.constant.Constants.REDIS_MSG;
import static com.ruoyi.common.constant.Constants.REDIS_MSG_TIME;

@ServerEndpoint("/appletSocket/{send}/{receiver}/{type}")
@Component
public class WebSocketServerController {

    private static final ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();

    private String send;

    // 实现服务器发送消息
    private static void sendMessage(String recv, String message) throws IOException {
        sessionPool.get(recv).getBasicRemote().sendText(message);
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("send") String send, @PathParam("receiver") String receiver, @PathParam("type") String type) throws IOException {
        this.send = send;
        sessionPool.put(send, session);

        System.out.println("有新连接加入！当前在线人数为" + sessionPool.size());

        RedisCache redisCache = SpringUtils.getBean("redisCache");
        ISysUserService sysUserService = SpringUtils.getBean("userServiceImpl");
        RedisTemplate redisTemplate = SpringUtils.getBean("redisTemplate");

        // 机构端连接
        if ("null".equals(receiver)) {
            // 获取所有的聊天用户对象
            Set<String> keys = redisTemplate.keys(("msg:" + REDIS_MSG + this.send + "&").concat("*"));
            assert keys != null;
            keys.forEach(s -> {
                SysUser sysUser = sysUserService.selectPatientById(Long.valueOf(s.substring(s.indexOf("&") + 1)));
                // 返回聊天用户信息
                try {
                    sendMessage(send, JSONObject.toJSONString(sysUser));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        } else {
            // 获取用户端或机构端离线时收到的消息并发送
            if ("app".equals(type)) {
                List<Object> list = redisCache.lGet("msg:" + REDIS_MSG + receiver + "&" + send, 0, redisCache.lGetListSize("msg:" + REDIS_MSG + receiver + "&" + send));

                // 用户端第一次连接，新用户
                if (!redisCache.hasKey("msg:" + REDIS_MSG + receiver + "&" + send) && sessionPool.containsKey(receiver)) {
                    // 发送新用户身份信息给机构端
                    sendMessage(receiver, JSONObject.toJSONString(sysUserService.selectDoctorById(Long.valueOf(send))));
                }
                preSend(list, send);
            } else {
                List<Object> list = redisCache.lGet("msg:" + REDIS_MSG + send + "&" + receiver, 0, redisCache.lGetListSize("msg:" + REDIS_MSG + send + "&" + receiver));
                preSend(list, send);
            }
        }
    }

    // 发送离线消息
    private void preSend(List<Object> list, String send) throws IOException {
        for (Object o : list) {
            JSONObject jsonObject = JSON.parseObject(o.toString());
            sendMessage(send, jsonObject.toJSONString());
        }
    }

    @OnClose
    public void onClose() {
        sessionPool.remove(send);
    }

    @OnMessage
    public String onMessage(String message) throws IOException {

        RedisCache redisCache = SpringUtils.getBean("redisCache");

        // 解析发送的消息
        JSONObject jsonObject = JSON.parseObject(message);

        if (jsonObject.containsKey("action")) {
            JSONObject action = new JSONObject();
            action.put("action", "pong");
            return action.toJSONString();
        }

        // 获取接收方
        JSONObject receiver = JSONObject.parseObject(jsonObject.getString("receiver"));

        // 获取发送方
        JSONObject sender = JSONObject.parseObject(jsonObject.getString("sender"));

        // 判断接收方是否在线
        if (receiver != null && sessionPool.containsKey(receiver.getString("id"))) {
            System.out.println("接收方在线");
            System.out.println("app".equals(jsonObject.getString("type")));
            // 判断发送方身份
            if ("app".equals(jsonObject.getString("type"))) {
                if (sender.containsKey("zd")) {
                    redisCache.lSet("msg:" + REDIS_MSG + receiver.getString("id") + "&" + sender.getString("id"), jsonObject.toJSONString(), REDIS_MSG_TIME);
                } else {
                    redisCache.lSet("msg:" + REDIS_MSG + receiver.getString("id") + "&" + this.send, jsonObject.toJSONString(), REDIS_MSG_TIME);
                }
            } else {
                redisCache.lSet("msg:" + REDIS_MSG + sender.getString("id") + "&" + receiver.getString("id"), jsonObject.toJSONString(), REDIS_MSG_TIME);
            }
            // 发送聊天消息
            sendMessage(receiver.getString("id"), jsonObject.toJSONString());

        } else {
            // 接收方不在线，只存储不发送
            System.out.println("接收方不在线");
            System.out.println("app".equals(jsonObject.getString("type")));
            if ("app".equals(jsonObject.getString("type"))) {
                if (sender.containsKey("zd")) {
                    redisCache.lSet("msg:" + REDIS_MSG + receiver.getString("id") + "&" + sender.getString("id"), jsonObject.toJSONString(), REDIS_MSG_TIME);
                } else {
                    redisCache.lSet("msg:" + REDIS_MSG + receiver.getString("id") + "&" + this.send, jsonObject.toJSONString(), REDIS_MSG_TIME);
                }
            } else {
                redisCache.lSet("msg:" + REDIS_MSG + sender.getString("id") + "&" + receiver.getString("id"), jsonObject.toJSONString(), REDIS_MSG_TIME);
            }
        }

        // 返回刚发送的消息给发送方
        return String.valueOf(jsonObject);
    }

}
